/*
 * Copyright (c) 2006-2021, Halo team
 *
 * SPDX-License-Identifier: GPLv3
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-09-11     Eywen        the first version
 */

#include "drv_temprature.h"
#include "common.h"
#include <math.h>

typedef struct ntc_rt_fiting_para_table{
    temperature_ntc_mode_t mode;
    ntc_rt_fitting_t rt_fitting_para;
}ntc_rt_fiting_table_t;

const static ntc_rt_fiting_table_t s_ntc_rt_fitting_para_list[ntc_mode_max] =
{
#ifdef NTC_ZM1460
    {
        ntc_mode_zm_1460,
        //        ntc_mode_zm_1460, /*Y = a + b·ln(X)*/
        //        {286.361217466148,  -22.2530889090078, 0, 0}
        {
            /*  CurveExpert Professional
                                Final Result [Sigmoidal Models/MMF]:
                                Equation  : (a*b + c*x^d)/(b + x^d)
                                    a = 3.262178440253401E+03
                                    b = 3.144869865684573E-01
                                    c = -1.002758708796864E+02
                                    d = 1.836412915059520E-01
                                Standard Error          : 1.756185195588159E+00
                                Correlation Coefficient : 9.998417905163157E-01
                            */
            3.262178440253401E+03, 3.144869865684573E-01,
            -1.002758708796864E+02, 1.836412915059520E-01
        }
    },
#endif
};

/* 从ntc拟合表中查找相应ntc型号的拟合表 */
static const ntc_rt_fitting_t *find_ntc_fitting_para_by_mode(temperature_ntc_mode_t mode)
{
    for(int i = 0; i < ntc_mode_max; i++){
        if(s_ntc_rt_fitting_para_list[i].mode == mode){
            return &(s_ntc_rt_fitting_para_list[i].rt_fitting_para);
        }
    }
    return NULL;
}

/* ntc电阻转换成温度函数 */
static double ntc_register_2_tempr(temperature_ntc_t *ntc, double regi)
{
    ASSERT_NULL(ntc);
    ASSERT_NULL(ntc->filtting_para);

    //return (a*exp(b*regi) + c*exp(d*regi));
    //return (a + b*log(regi));
#ifdef NTC_ZM1460
    double a, b, c, d;
    a = ntc->filtting_para->a;
    b = ntc->filtting_para->b;
    c = ntc->filtting_para->c;
    d = ntc->filtting_para->d;
    d = pow(regi, d);
    return (a*b + c*d)/(b + d);
#else
#error "ntc sensor mode unknow"
    return 0;
#endif
}


/* ntc传感器的adc采样值转换成电阻值 */
static double ntc_adc_sample_2_rigister(temperature_ntc_t *ntc, uint32_t adc_sample)
{
    ASSERT_NULL(ntc);

    return (adc_sample *ntc->resistance_pullup*1.0)/(ntc->adc_max - adc_sample);
}

/* 读取adc，将adc值转换成电阻值再转换成温度值返回 */
static float ntc_temperature(temperature_ntc_t *ntc)
{
    ASSERT_NULL(ntc);
    ASSERT_NULL(ntc->adc_dev);

    uint32_t adc_sample;
    double ntc_regi;

    /* 从adc中读取采集值 */
    adc_sample =  rt_adc_read(ntc->adc_dev, ntc->adc_dev_channel);
    /* 通过电路关系将采集值转换成电阻值 */
    ntc_regi = ntc_adc_sample_2_rigister(ntc, adc_sample);
    //debug_info("adc sample: %u ntc reg: %u", adc_sample, (uint32_t)ntc_regi);
    /* 将电阻值转换成温度值 */
    return (float)ntc_register_2_tempr(ntc, ntc_regi);
}


/* 初始化ntc温度传感器接口  */
bool ntc_temperature_init(temperature_ntc_t *ntc, const char *adc_dev_name,
                          uint32_t adc_channle, uint8_t adc_bits,
                          temperature_ntc_mode_t mode, uint32_t resistance_up)
{
    ASSERT_NULL(ntc);
    ASSERT_NULL(adc_dev_name);

    /* 查找adc驱动 */
    ntc->adc_dev = (rt_adc_device_t)rt_device_find(adc_dev_name);
    if(ntc->adc_dev == RT_NULL){
        debug_error("NTC %s driver not found", adc_dev_name);
        return false;
    }

    /* 通过型号查找参数表中的具体型号参数 */
    ntc->filtting_para = find_ntc_fitting_para_by_mode(mode);
    if(ntc->filtting_para == NULL){
        debug_error("NTC %d fitting parameter not found", mode);
        ntc->adc_dev = RT_NULL;
        return false;
    }

    ntc->adc_max = ((((uint32_t)0x01) << adc_bits) - 1);
    ntc->adc_dev_name = adc_dev_name;
    ntc->adc_dev_channel = adc_channle;
    ntc->mode = mode;
    ntc->resistance_pullup = resistance_up;

    /* 使能adc通道设备 */
    if(rt_adc_enable(ntc->adc_dev, adc_channle) != RT_EOK){
        debug_error("adc %s enable faild", adc_dev_name);
    }

    return false;
}

/* NTC 温度传感器操作接口 */
const static temperature_ntc_ops_t s_temperature_ntc_ops = {
    .init = ntc_temperature_init,
    .temperature = ntc_temperature,
};

/* 通过温度传感器的型号来返回传感器的操作接口 */
const void *find_temerature_ops_by_mode(temperature_type_t type)
{
    switch (type){
    case temperature_type_ntc:
        return &s_temperature_ntc_ops;
    default:
        debug_error("No driver interface of this model was found");
        return NULL;
    }
}




